import {
	createApp,
	onMounted,
	reactive,
	ref,
	watch
} from "/plug/vue.esm-browser.js"

createApp({
	setup() {
		// 连接状态
		const Socket = io.connect('http://localhost:3000');
		// 这里最好使用响应式的方法声明，可以保证数据能够被及时的接收
		const connectState = reactive({
			State: 0,
			Text: ["未连接", "已连接", "连接断开", "连接错误"],
			color: ["#3376db", "#4ce400", "#f1f100", "#f10000"],
			consoleMessage: ["控制台显示:"],
		});
		// 发送状态
		const sendState = reactive({
			// 当前房间名称
			room: "public",
			// 房间对象列表
			roomlist: [{
				RoomId: "public",
				RoomName: "公开房间",
			}, {
				RoomId: "test",
				RoomName: "测试房间",
			}],
			// 消息对象列表
			SendMessageList: [],
			ReceiveMessageList: [],
			eventList: [],
		});

		// 发送模板
		const Stemplate = reactive([{
			name: "测试模板1",
			room: "test",
			sendID: "test1",
			receiveID: "",
			message: "这是测试用的消息",
			sendType: "room",
		}]);


		// 发送设置
		// 作为模板使用，尽量不要污染数据
		const sendSet = reactive({
			name: `模板${(Stemplate.length+1)}`,
			room: "public",
			sendID: "admin",
			receiveID: "",
			message: "",
			sendType: "",
		});



		// 添加值和观察者，观察值的变化
		const Sindex = ref(0);
		watch(
			() => Sindex.value,
			(newValue, oldValue) => {
				if (newValue != -1) {
					let {
						room,
						sendID,
						receiveID,
						message,
						sendType
					} = Stemplate[newValue];
					// 应用模板
					sendSet.name = `模板${(Stemplate.length+1)}`;
					sendSet.room = room;
					sendSet.sendID = sendID;
					sendSet.receiveID = receiveID;
					sendSet.message = message;
					sendSet.sendType = sendType;
				} else {
					sendSet.name = `模板${(Stemplate.length+1)}`;
				}

				return newValue;
			}, {
				immediate: true
			} // 立即执行回调函数    
		);




		// 消息对象类
		class Message {
			// 发送房间，发送名称，发送数据，发送类型
			// 这里只需要记录发送者名称，不需要记录是否是本人发送，后面可以通过对比得到
			constructor(sendBody) {
				this.room = sendBody.room;
				this.sendID = sendBody.sendID;
				this.receiveID = sendBody.receiveID;
				this.message = sendBody.message;
				this.sendType = sendBody.sendType;
				// 发送次数
				this.sendNum = 0;
				// 发送状态
				this.sendStatus = "no";
				// 显示模式
				this.flagShow = true;
				// 发送时间(记录时间)
				this.time = [];
				this.time.push(new Date())
			}

			// TS:赋值模板
			// let sendMessage = new Message({
			// 	room: "",
			// 	sendID: "",
			// 	receiveID: "",
			// 	message: "",
			// 	sendType: "", //发送类型为系统类型
			// });

			// 发送方法
			// 将该条信息进行发送
			send() {
				// 增加发送次数
				this.sendNum++;
				// 发送数据
				// 这里，sokcet发送接收的行为，就是这样使用的
				// 一端使用emit方法，发送数据
				// 另一端,使用同名的on方法接收数据
				// 和之前不同的是,之前只能是客户端向服务器先请求
				// 服务器再发送数据给前端
				// 现在可以由服务器或者客户端任意发送请求,然后另一端处理这个请求
				// 你向你的qq好友发送了一个消息,如果好友暂时没有看到,会过一段事件再回消息
				// 这个时候我们不清楚,好友何时会回消息,所以聊天的数据,一定是由服务器转发给我们
				// 也就是说需要服务器先发送数据,客户端接收
				Socket.emit(this.sendType, {
					sendID: this.sendID,
					receiveID: this.receiveID,
					message: this.message,
					room: this.room,
					sendType: this.sendType,
				}, (response) => {
					this.sendStatus = response.status;
				});
			}

			// 保存方法
			// 将该条信息进行保存(数组中)
			saveMessgae(arr) {
				arr.push(this);
			}

			// 获取时间方法
			getTime() {
				return this.time.at(-1).toLocaleDateString('en-GB') + "\t" + this.time.at(-1)
					.toLocaleTimeString('it-IT');
			}

			// 获取发送状态
			getStatus() {
				let Status = this.sendStatus == 'ok' ? true : false;
				if (Status) {
					return `<b style="color:${connectState.color[1]}">已发送</b>`;
				} else {
					return `<b style="color:${connectState.color[3]}">未发送</b>`;
				}

			}
		}

		// 客户端响应事件
		onMounted(() => {
			// 服务器连接成功事件
			Socket.on("connect", () => {
				connectState.State = 1;
				consoleSend("服务器连接成功!");
			});

			// 服务器连接失败事件
			Socket.on("connect_error", () => {
				connectState.State = 3;
				//连接错误，尝试重新连接
				setTimeout(() => {
					consoleSend(`连接错误，正在尝试重新连接`);
					Socket.connect();
				}, 3000);
			});

			// 服务器断开事件
			Socket.on("disconnect", (reason) => {
				connectState.State = 2;
				consoleSend("服务器断开!");
			});


			// 获取来自服务的所有响应
			Socket.onAny((event, sendBody) => {
				// 添加至数组
				let ReceiveMessage = new Message(sendBody);
				ReceiveMessage.saveMessgae(sendState.ReceiveMessageList);
			});

			//来自服务器的私聊请求
			Socket.on('PC', (reason) => {
				let ReceiveMessage = new Message(sendBody);
				ReceiveMessage.saveMessgae(sendState.ReceiveMessageList);
			});

			// TS
			// 每过十秒钟向后端查询服务器目前情况
			let getServerMessage = new Message({
				sendID: "system",
				receiveID: "polling",
				room: "getServerMessage",
				message: "",
				sendType: "system:polling:getServerMessage", //发送类型为系统类型
			});
			getServerMessage.send();

			// socket路由使用冒号分割
			Socket.on('system:polling:getServerMessage', (reason) => {
				console.log(...reason.message);
				sendState.eventList = [];
				sendState.eventList.push(...reason.message);
				// 设置默认选中
				// sendSet.sendType = reason.message[0];
			});
			// setInterval(() => {
			// 	// 只有当已连接时才向后端轮询
			// 	if (connectState.State == 1) {
			// 		getServerMessage.send();
			// 	}
			// }, 1000 * 10)

			// 获取当前登录状态
			let getSession = new Message({
				sendID: "system",
				receiveID: "get",
				room: "getSession",
				message: "",
				sendType: "system:get:getSession",
			});
			getSession.send();

			// 接收时间
			// 当服务器发送数据到前端时，触发这个事件
			// 为什么触发这个事件？因为这个事件的名称叫做system:get:getSession
			Socket.on('system:get:getSession', (reason) => {
				let userMessage = reason.message.user;
				// 通过session判断用户是否已经登录
				if (userMessage) {
					// 如果用户已经登录，重新保存已登录的相关信息
					consoleSend("用户已登录");
					Simulate.login = true;
					console.log(userMessage);
					Simulate.user = userMessage;
					// 向后端请求绑定socket连接和账户信息
					let sendMessage = new Message({
						sendID: "system",
						receiveID: "bind",
						room: "user",
						message: "请求绑定socket连接和用户信息",
						sendType: "system:bind:user",
					});
					sendMessage.send();
					sendMessage.saveMessgae(sendState.SendMessageList);
				} else {
					consoleSend("用户未登录");
					Simulate.user = {};
					Simulate.login = false;
				}
			});



			// 系统绑定事件
			Socket.on('system:bind:user', (reason) => {
				if (reason.room) {
					Simulate.socketOnline = true;
					console.log("成功绑定socket连接和用户信息");
				} else {
					Simulate.socketOnline = false;
					console.log("未能成功绑定socket连接和用户信息");
				}
			});



			// 向后端获取模板列表
			axios.get("/test/template").then((rls) => {
				let {
					result,
					data,
					describe
				} = rls.data;

				if (result) {
					for (let key in data) {
						Stemplate.push(data[key]);
					}
				} else {
					consoleSend("获取模板列表失败");
					consoleSend(describe);
				}
			}).catch((e) => {
				consoleSend("获取模板列表失败");
				consoleSend(e);
			});
		});
		// 控制台输出方法
		let consoleSend = (text) => {
			connectState.consoleMessage.push(text + "");
		}
		//定义发送和关闭方法 
		let close = () => {
			if (Socket.connected) {
				consoleSend("关闭socket连接")
				Socket.disconnect()
			} else {
				consoleSend("无法重复断开!")
			}
		}
		let send = () => {
			// 新建一个发送对象,并调用其发送方法
			let sendMessage = new Message(sendSet);
			sendMessage.send();
			sendMessage.saveMessgae(sendState.SendMessageList);
		}
		let again = () => {
			consoleSend("服务器重新连接")
			Socket.connect();
			//连接成功后更新session
			let getSession = new Message({
				sendID: "system",
				receiveID: "get",
				room: "getSession",
				message: "",
				sendType: "system:get:getSession",
			});
			getSession.send();
		}
		let save = () => {
			axios.post("/test/template", sendSet).then((rls) => {
				let {
					result,
					data,
					describe
				} = rls.data;
				if (result) {
					consoleSend(`保存模板(${data.name})成功`);
					Stemplate.push(data);
				} else {
					consoleSend("保存模板失败");
					consoleSend(describe);
				}
			}).catch((e) => {
				consoleSend("保存模板列表失败");
				consoleSend(e);
			});
		}


		// 模拟登录对象
		const Simulate = reactive({
			login: false, //是否已登录
			username: "admin", //登录账户
			password: "123456", //登录密码
			socketOnline: false, //socket是否已经绑定
			user: {}, //登录数据包
		})


		// 查看房间列表
		let showRoomList = () => {
			let sendMessage = new Message({
				sendID: Simulate.username,
				receiveID: Simulate.password,
				room: Simulate.socketOnline,
				message: Simulate.user.groups,
				sendType: "system",
			});
			sendMessage.saveMessgae(sendState.SendMessageList);
		}

		// 查看好友列表
		let showFriendList = () => {
			let sendMessage = new Message({
				sendID: Simulate.username,
				receiveID: Simulate.password,
				room: Simulate.socketOnline,
				message: Simulate.user.friendId.friends,
				sendType: "system",
			});
			sendMessage.saveMessgae(sendState.SendMessageList);
		}

		// 触发登录事件
		let login = () => {
			axios.post("/users/login", {
				username: Simulate.username,
				password: Simulate.password
			}).then((rls) => {
				let {
					result,
					data,
					describe
				} = rls.data;

				console.log(rls.data);
				// 判断是否登录成功
				if (result) {
					consoleSend("模拟登录成功");
					Simulate.login = true;
					Simulate.user = data;

					// 向后端请求绑定socket连接和账户信息
					let sendMessage = new Message({
						sendID: "system",
						receiveID: "bind",
						room: "user",
						message: "请求绑定socket连接和用户信息",
						sendType: "system:bind:user",
					});
					sendMessage.send();
					sendMessage.saveMessgae(sendState.SendMessageList);
				} else {
					consoleSend("模拟登录失败");
					consoleSend(describe);
				}
			}).catch((e) => {
				consoleSend("模拟登录失败");
				consoleSend(e);
			});
		}



		return {
			Sindex, //模板选择的下标
			save, //保存模板的方法
			close, //关闭方法
			send, //发送方法
			again, //重连方法
			sendSet, //发送配置
			Stemplate, //模板对象
			sendState, //发送相关对象
			connectState, //连接相关对象
			Simulate, //模拟登录数据
			login, //模拟登录事件
			showRoomList, //查看账户房间列表
			showFriendList, //查看账户好友列表
		}
	}
}).mount('#app');